home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 151-175 / disk_172 / spiff / output.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  11KB  |  583 lines

  1. /*                        Copyright (c) 1988 Bellcore
  2. **                            All Rights Reserved
  3. **       Permission is granted to copy or use this program, EXCEPT that it
  4. **       may not be sold for profit, the copyright notice must be reproduced
  5. **       on copies, and credit should be given to Bellcore where it is due.
  6. **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
  7. */
  8.  
  9.  
  10. #ifndef lint
  11. static char rcsid[]= "$Header: output.c,v 1.1 88/09/15 11:33:52 daniel Rel $";
  12. #endif
  13.  
  14. #include <stdio.h>
  15.  
  16. #ifdef M_TERMINFO
  17. #include <curses.h>
  18. #include <term.h>
  19. #endif
  20.  
  21. #ifdef M_TERMCAP
  22. #ifdef XENIX
  23. #include <tcap.h>
  24. #endif
  25. #endif
  26.  
  27. #include "misc.h"
  28. #include "flagdefs.h"
  29. #include "edit.h"
  30. #include "line.h"
  31. #include "token.h"
  32.  
  33. static int _O_need_init = 1;
  34. static int _O_st_ok = 0;
  35. static int _O_doing_ul = 0;
  36. static    char *_O_st_tmp;
  37. #ifdef M_TERMCAP
  38. static    char _O_startline[Z_WORDLEN];
  39. static    char _O_endline[Z_WORDLEN];
  40. #endif
  41.  
  42. static void
  43. _O_st_init()
  44. {
  45.     char termn[Z_WORDLEN];
  46. #ifdef M_TERMCAP
  47.     static    char entry[1024];
  48. #endif
  49.     extern char *getenv ();
  50.  
  51.     /*
  52.     **    see if standard out is a terminal
  53.     */
  54.     if (!isatty(1))
  55.     {
  56.         _O_need_init = 0;
  57.         _O_st_ok = 0;
  58.         return;
  59.     }
  60.  
  61. #if amiga
  62.     if (NULL == (_O_st_tmp = "ansi"))
  63. #else
  64.     if (NULL == (_O_st_tmp = (char*) getenv("TERM")))
  65. #endif
  66.     {
  67.         Z_complain("can't find TERM entry in environment\n");
  68.         _O_need_init = 0;
  69.         _O_st_ok = 0;
  70.         return;
  71.     }
  72.     (void) strcpy(termn,_O_st_tmp);
  73.  
  74. #ifdef M_TERMCAP
  75.     if (1 != tgetent(entry,termn))
  76.     {
  77.         Z_complain("can't get TERMCAP info for terminal\n");
  78.         _O_need_init = 0;
  79.         _O_st_ok = 0;
  80.         return;
  81.     }
  82.  
  83.     _O_st_tmp = _O_startline;
  84.     _O_startline[0] = '\0';
  85.     tgetstr("so",&_O_st_tmp);
  86.  
  87.     _O_st_tmp = _O_endline;
  88.     _O_endline[0] = '\0';
  89.     tgetstr("se",&_O_st_tmp);
  90.  
  91.     _O_st_ok = (strlen(_O_startline) > 0) && (strlen(_O_endline) > 0);
  92. #endif
  93.  
  94. #ifdef M_TERMINFO
  95.     setupterm(termn,1,&_O_st_ok);
  96. #endif
  97.     _O_need_init = 0;
  98. }
  99.  
  100. void
  101. O_cleanup()
  102. {
  103.     /*
  104.     **    this probably isn't necessary, but in the
  105.     **    name of compeleteness.
  106.     */
  107. #ifdef M_TERMINFO
  108.     resetterm();
  109. #endif
  110. }
  111.  
  112. static void
  113. _O_start_standout()
  114. {
  115.     if (_O_need_init)
  116.     {
  117.         _O_st_init();
  118.     }
  119.     if (_O_st_ok)
  120.     {
  121. #ifdef M_TERMCAP
  122.         (void) printf("%s",_O_startline);
  123. #endif 
  124. #ifdef M_TERMINFO
  125.         vidattr(A_STANDOUT);
  126. #endif
  127.     }
  128.     else
  129.     {
  130.         _O_doing_ul = 1;
  131.     }
  132. }
  133.  
  134. static void
  135. _O_end_standout()
  136. {
  137.     if (_O_need_init)
  138.     {
  139.         _O_st_init();
  140.     }
  141.     if (_O_st_ok)
  142.     {
  143. #ifdef M_TERMCAP
  144.         (void) printf("%s",_O_endline);
  145. #endif 
  146. #ifdef M_TERMINFO
  147.         vidattr(0);
  148. #endif
  149.     }
  150.     else
  151.     {
  152.         _O_doing_ul = 0;
  153.     }
  154. }
  155.  
  156. static void
  157. _O_pchars(line,start,end)
  158. char *line;
  159. int start,end;
  160. {
  161.     int cnt;
  162.  
  163.     for(cnt=start;cnt < end; cnt++)
  164.     {
  165.         if (_O_doing_ul)
  166.         {
  167.             (void) putchar('_');
  168.             (void) putchar('\b');
  169.         }
  170.         (void) putchar(line[cnt]);
  171.     }
  172. }
  173.  
  174.  
  175. /*
  176. **    convert a 0 origin token number to a 1 orgin token
  177. **        number or 1 origin line number as appropriate
  178. */
  179. static
  180. _O_con_line(numb,flags,filenum)
  181. int numb, flags,filenum;
  182. {
  183.     if (flags & U_TOKENS)
  184.     {
  185.         return(numb+1);
  186.     }
  187.     else
  188.     {
  189.         /*
  190.         **     check to make sure that this is a real
  191.         **    line number. if not, then return 0
  192.         **    on rare occasions, (i.e. insertion/deletion
  193.         **    of the first token in a file) we'll get
  194.         **    line numbers of -1.  the usual look-up technique
  195.         **    won't work since we have no lines before than 0.
  196.         */
  197.         if (numb < 0)
  198.             return(0);
  199.         /*
  200.         **    look up the line number the token and then
  201.         **    add 1 to make line number 1 origin
  202.         */
  203.         return(L_tl2cl(filenum,numb)+1);
  204.     }
  205. }
  206.  
  207. static char *
  208. _O_convert(ptr)
  209. char *ptr;
  210. {
  211.     static char spacetext[Z_WORDLEN];
  212.  
  213.     if (1 == strlen(ptr))
  214.     {
  215.         switch (*ptr)
  216.         {
  217.             default:
  218.                 break;
  219.             case '\n' :
  220.                 (void) strcpy(spacetext,"<NEWLINE>");
  221.                 return(spacetext);
  222.             case '\t' :
  223.                 (void) strcpy(spacetext,"<TAB>");
  224.                 return(spacetext);
  225.             case ' ' :
  226.                 (void) strcpy(spacetext,"<SPACE>");
  227.                 return(spacetext);
  228.         }
  229.                 
  230.     }
  231.     return(ptr);
  232. }
  233.  
  234. static char*
  235. _O_get_text(file,index,flags)
  236. int file,index,flags;
  237. {
  238.     static char buf[Z_LINELEN*2];    /* leave lots of room for both
  239.                         the token text and the
  240.                         chatter that preceeds it */
  241.     char *text;
  242.     K_token tmp;
  243.  
  244.     if (flags & U_TOKENS)
  245.     {
  246.         tmp = K_gettoken(file,index);
  247.         text = _O_convert(K_gettext(tmp));
  248.         (void) sprintf(buf,"%s -- line %d, character %d\n",
  249.                 text,
  250.                 /*
  251.                 **    add 1 to make output start at line 1 
  252.                 **    and character numbers start at 1
  253.                 */
  254.                 L_tl2cl(file,K_getline(tmp))+1,
  255.                 K_getpos(tmp)+1);
  256.         return(buf);
  257.     }
  258.     else
  259.     {
  260.         return(L_gettline(file,index));
  261.     }
  262. }
  263. #define    _O_APP        1
  264. #define _O_DEL        2
  265. #define _O_CHA        3
  266. #define _O_TYPE_E    4
  267.  
  268. static void
  269. _O_do_lines(start,end,file)
  270. int start,end,file;
  271. {
  272.     int cnt;
  273.     int lastline = -1;
  274.     int nextline;
  275.     K_token nexttoken;
  276.     for (cnt=start;cnt <= end; cnt++)
  277.     {
  278.         nexttoken = K_get_token(file,cnt);
  279.         nextline = K_getline(nexttoken);
  280.         if (lastline != nextline)
  281.         {
  282.             int lastone,lastchar;
  283.             K_token lasttok;
  284.             char linetext[Z_LINELEN+1];    /* leave room for
  285.                                terminator */
  286.             if (0 == file)
  287.             {
  288.                 (void) printf("< ");
  289.             }
  290.             else
  291.             {
  292.                 (void) printf("> ");
  293.             }
  294.  
  295.             /*
  296.             **    put loop here if you want to print
  297.             **    out any intervening lines that don't
  298.             **    have any tokens on them
  299.             */
  300.  
  301.             /*
  302.             **    following line is necessary because
  303.             **    L_gettline is a macro, and can't be passed
  304.             */
  305.             (void) strcpy(linetext,L_gettline(file,nextline));
  306.             _O_pchars(linetext,0,K_getpos(nexttoken));
  307.             _O_start_standout();
  308.             /*
  309.             **     look for last token on this line to be
  310.             **    highlighted
  311.             */
  312.             for ( lastone=cnt,lasttok = K_get_token(file,lastone);
  313.                   (lastone<=end)&&(nextline == K_getline(lasttok));
  314.                 lastone++,lasttok = K_get_token(file,lastone))
  315.             {
  316.             }
  317.             lastone--;
  318.             lasttok = K_get_token(file,lastone);
  319.             lastchar = K_getpos(lasttok)
  320.                     + strlen(K_gettext(lasttok));
  321.             _O_pchars(linetext,K_getpos(nexttoken),lastchar);
  322.             _O_end_standout();
  323.             _O_pchars(linetext,lastchar,strlen(linetext));
  324.             
  325.             lastline = nextline;
  326.         }
  327.     }
  328. }
  329.  
  330. void
  331. O_output(start,flags)
  332. E_edit start;
  333. int flags;
  334. {
  335.     int type = _O_TYPE_E;    /* initialize to error state
  336.                 ** this is to make sure that type is set
  337.                 ** somewhere
  338.                 */
  339.     int t_beg1, t_beg2, t_end1, t_end2; /* token numbers */
  340.     int first1, last1, first2, last2;
  341.  
  342.     E_edit ep, behind, ahead, a, b;
  343.  
  344.     /*
  345.     **    reverse the list of edits
  346.     */
  347.     ahead = start;
  348.     ep = E_NULL;
  349.     while (ahead != E_NULL) {
  350.         /*
  351.         **    set token numbers intentionally out of range
  352.         **        as boilerplate
  353.         */
  354.         t_beg1 = t_beg2 = t_end1 = t_end2 = -1;
  355.         /*
  356.         **    edit script is 1 origin, all of
  357.         **     our routines are zero origin
  358.         */
  359.         E_setl1(ahead,(E_getl1(ahead))-1);
  360.         E_setl2(ahead,(E_getl2(ahead))-1);
  361.  
  362.         behind = ep;
  363.         ep = ahead;
  364.         ahead = E_getnext(ahead);
  365.         E_setnext(ep,behind);
  366.     }
  367.  
  368.     /*
  369.     **    now run down the list and collect the following information
  370.     **    type of change (_O_APP, _O_DEL or _O_CHA)
  371.     **    start and length for each file
  372.     */
  373.     while (ep != E_NULL)
  374.     {
  375.         b = ep;
  376.         /*
  377.         **    operation always start here
  378.         */
  379.         t_beg1 = E_getl1(ep);
  380.         /*
  381.         **    any deletions will appear before any insertions,
  382.         **    so, if the first edit is an E_INSERT, then this
  383.         **    this is an _O_APP
  384.         */
  385.         if (E_getop(ep) == E_INSERT)
  386.             type = _O_APP;
  387.         else {
  388.             /*
  389.             **    run down the list looking for the edit
  390.             **    that is not part of the current deletion
  391.             */    
  392.             do {
  393.                 a = b;
  394.                 b = E_getnext(b);
  395.             } while ((b != E_NULL) &&
  396.                  (E_getop(b) == E_DELETE) &&
  397.                  ((E_getl1(b)) == ((E_getl1(a))+1)));
  398.             /*
  399.             **    if we have an insertion at the same place
  400.             **    as the deletion we just scanned, then
  401.             **    this is a change
  402.             */
  403.             if ((b != E_NULL) &&
  404.                 ((E_getop(b)) == E_INSERT) &&
  405.                 ((E_getl1(b))==(E_getl1(a))))
  406.             {
  407.                 type = _O_CHA;
  408.             }
  409.             else
  410.             {
  411.                 type = _O_DEL;
  412.             }
  413.             /*
  414.             **    set up start and length information for
  415.             **    first file
  416.             */
  417.             t_end1 = E_getl1(a);
  418.             /*
  419.             **    move pointer to beginning of insertion
  420.             */
  421.             ep = b;
  422.             /*
  423.             **    if we are showing only a deletion,
  424.             **    then we're all done, so skip ahead
  425.             */ 
  426.             if (_O_DEL == type)
  427.             {
  428.                 t_beg2 = E_getl2(a);
  429.                 t_end2 = -1;    /* dummy number, won't
  430.                             ever be printed */
  431.                            
  432.                 goto skipit;
  433.             }
  434.         }
  435.         t_beg2 = E_getl2(ep);
  436.         t_end2 = t_beg2-1;
  437.         /*
  438.         **    now run down the list lookingfor the
  439.         **    end of this insertion and keep count
  440.         **    of the number of times we step along
  441.         */
  442.         do {
  443.             t_end2++;
  444.             ep = E_getnext(ep);
  445.         } while ((ep != E_NULL) && ((E_getop(ep)) == E_INSERT) &&
  446.                     ((E_getl1(ep)) == (E_getl1(b))));
  447.  
  448. skipit:;
  449.         if (flags & U_TOKENS)
  450.         {
  451.             /*
  452.             **    if we are dealing with tokens individually,
  453.             **    then just print then set printing so
  454.             */
  455.                 first1 = t_beg1;
  456.                 last1 = t_end1;
  457.                 first2 = t_beg2;
  458.                 last2 = t_end2;
  459.         }
  460.         else
  461.         {
  462.             /*
  463.             **    we are printing differences in terms of lines
  464.             **    so find the beginning and ending lines of the
  465.             **    changes and print header in those terms
  466.             */
  467.             if ( t_beg1 >= 0)
  468.                 first1 = K_getline(K_get_token(0,t_beg1));
  469.             else
  470.                 first1 = t_beg1;
  471.  
  472.             if ( t_end1 >= 0)
  473.                 last1 = K_getline(K_get_token(0,t_end1));
  474.             else
  475.                 last1 = t_end1;
  476.  
  477.             if ( t_beg2 >= 0)
  478.                 first2 = K_getline(K_get_token(1,t_beg2));
  479.             else
  480.                 first2 = t_beg2;
  481.  
  482.             if ( t_end2 >= 0)
  483.                 last2 = K_getline(K_get_token(1,t_end2));
  484.             else
  485.                 last2 = t_end2;
  486.  
  487.         }
  488.         /*
  489.         **    print the header for this difference
  490.         */
  491.         (void) printf("%d",_O_con_line(first1,flags,0));
  492.         switch (type)
  493.         {
  494.         case _O_APP :
  495.             (void) printf("a%d",_O_con_line(first2,flags,1));
  496.             if (last2 > first2)
  497.             {
  498.                 (void) printf(",%d",_O_con_line(last2,flags,1));
  499.             }
  500.             (void) printf("\n");
  501.             break;
  502.         case _O_DEL :
  503.             if (last1 > first1)
  504.             {
  505.                 (void) printf(",%d",_O_con_line(last1,flags,0));
  506.             }
  507.             (void) printf("d%d\n",_O_con_line(first2,flags,1));
  508.             break;
  509.         case _O_CHA :
  510.             if (last1 > first1)
  511.             {
  512.                 (void) printf(",%d",_O_con_line(last1,flags,0));
  513.             }
  514.             (void) printf("c%d",_O_con_line(first2,flags,1));
  515.             if (last2 > first2)
  516.             {
  517.                 (void) printf(",%d",_O_con_line(last2,flags,1));
  518.             }
  519.             (void) printf("\n");
  520.             break;
  521.         default:
  522.             Z_fatal("type in O_output wasn't set\n");
  523.         }
  524.         if (_O_DEL == type || _O_CHA == type)
  525.         {
  526.             if (flags & U_TOKENS)
  527.             {
  528.                 int cnt;
  529.                 for(cnt=first1;cnt <= last1; cnt++)
  530.                 {
  531.         (void) printf("< %s",
  532.                             _O_get_text(0,cnt,flags));
  533.                 }
  534.             }
  535.             else
  536.             {    
  537.                 _O_do_lines(t_beg1,t_end1,0);
  538.             }
  539.         }
  540.         if (_O_CHA == type)
  541.         {
  542.             (void) printf("---\n");
  543.         }
  544.         if (_O_APP == type || _O_CHA == type)
  545.         {
  546.             if (flags & U_TOKENS)
  547.             {
  548.                 int cnt;
  549.                 for(cnt=first2;cnt <= last2; cnt++)
  550.                 {
  551.                     (void) printf("> %s",
  552.                         _O_get_text(1,cnt,flags));
  553.                 }
  554.             }
  555.             else
  556.             {
  557.                 _O_do_lines(t_beg2,t_end2,1);
  558.             }
  559.         }
  560.     }
  561.     O_cleanup();
  562.     return;
  563. }
  564.  
  565. #if amiga
  566. tgetent ()
  567. {
  568.     return (1);
  569. }
  570.  
  571. tgetstr (str, where)
  572. char *str;
  573. char **where;
  574. {
  575.     if (strcmp (str, "so")) {
  576.         *where = "\033[7m";
  577.     } else if (strcmp (str, "se")) {
  578.         *where = "\033[m";
  579.     }
  580. }
  581.  
  582. #endif
  583.